<?php
/**
 * Manages the global variables for the context of the page.
 * Applications utilizing this file: Vanilla;
 *
 * Copyright 2003 Mark O'Sullivan
 * This file is part of Lussumo's Software Library.
 * Lussumo's Software Library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
 * Lussumo's Software Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License along with Vanilla; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * The latest source code is available at www.lussumo.com
 * Contact Mark O'Sullivan at mark [at] lussumo [dot] com
 *
 * @author Mark O'Sullivan
 * @copyright 2003 Mark O'Sullivan
 * @license http://lussumo.com/community/gpl.txt GPL 2
 * @package Framework
 * @version 1.1.2
 */

/**
 * Manages the global variables for the context of the page.
 * @package Framework
 */
class Context
{
   // Public Properties
    /**
     * @var MessageCollector Used to collect and display warning message
     */
    var $WarningCollector;

    /**
     * @var ErrorManager Used to collect and display fatal error
     */
    var $ErrorManager;

    /**
     * @var MessageCollector Collect sql request to display for debugging
     */
    var $SqlCollector;

    /**
     * @var string Url of the current page (this should be hard-coded by each page since php server vars are unreliable)
     */
    var $SelfUrl;

    /**
     * @var string Url to the style folder
     */
    var $StyleUrl = '';

    /**
     * @var string Current Mode ( Debug, Release, etc...)
     */
   var $Mode;

    /**
     * @var string Body tag attributes - used by themes/head.php.
     */
    var $BodyAttributes = '';

    /**
     * @var string Title of the page; used for the title tag.
     */
    var $PageTitle = '';

    /**
     * @var StringManipulator
     */
    var $StringManipulator;

    /**
     * @var array
     */
    var $Dictionary = array();

    /**
     * @var array
     */
    var $Configuration = array();

    /**
     * @var array
     */
    var $DelegateCollection = array();

    /**
     * @var array Map the table references to the forum table names (minus the table prefix).
     */
    var $DatabaseTables = array();

    /**
     * @var array Map the column ceferences to the forum Column names.
     */
    var $DatabaseColumns = array();

    /**
     * @var array An associative array of variables that can be passed down through the context object into various parts of the application
     */
    var $PassThruVars = array();

    static private $instance = null;

    static function getInstance()
    {
        if (self::$instance == null) {
            self::$instance = new Context();
        }

        return self::$instance;
    }

    private function __clone()
    {
    }

    /**
     * Constructor.
     * @return void
     */
    private function __construct()
    {
        // Yes yes I know, ugly, I'll fix this later
        global $Configuration;
        $this->Configuration = $Configuration;
        $this->CommentFormats[] = 'Text';

        // Current Mode
        $this->Mode = ForceIncomingCookieString('Mode', '');

        // Url of the current page (this should be hard-coded by each page since php server vars are unreliable)
        $this->SelfUrl = ForceString($Configuration['SELF_URL'], 'index.php');

        // Instantiate a SqlCollector (for debugging)
        $this->SqlCollector = new MessageCollector();
        $this->SqlCollector->CssClass = 'Sql';

        // Instantiate a Warning collector (for user errors)
        $this->WarningCollector = new MessageCollector();

        // Instantiate an Error manager (for fatal errors)
        $this->ErrorManager = new ErrorManager();

        // Instantiate the string manipulation object
        $this->StringManipulator = new StringManipulator($this->Configuration);
        // Add the plain text manipulator
        $TextFormatter = new TextFormatter();
        $this->StringManipulator->AddManipulator($Configuration['DEFAULT_FORMAT_TYPE'], $TextFormatter);
    }

     /**
      * Add a function to a delegation
      * @param string $ClassName
      * @param string $DelegateName
      * @param string $FunctionName
      * @return void
      * @link http://lussumo.com/docs/doku.php?id=vanilla:development:delegation
      */
    function AddToDelegate($ClassName, $DelegateName, $FunctionName)
    {
        if (!isset($this->DelegateCollection[$ClassName])) {
            $this->DelegateCollection[$ClassName] = array();
        }
        if (!isset($this->DelegateCollection[$ClassName][$DelegateName])) {
             $this->DelegateCollection[$ClassName][$DelegateName] = array();
        }
        $this->DelegateCollection[$ClassName][$DelegateName][] = $FunctionName;
    }

    /**
     * Parse a string; mainly used for output filter.
     * @param string $String
     * @param mixed $Object Object related to the string in some way
     * @param string $Format The string-formatter that will parse the string.
     * @param string $FormatPurpose Use the FORMAT_STRING_FOR_DISPLAY constant.
     * @return string
     */
    function FormatString($String, $Object, $Format, $FormatPurpose)
    {
        $sReturn = $this->StringManipulator->Parse($String, $Object, $Format, $FormatPurpose);
        // Now pass the string through global formatters
        $sReturn = $this->StringManipulator->GlobalParse($sReturn, $Object, $FormatPurpose);
        return $sReturn;
    }

    function GetDefinition($Code)
    {
        if (isset($this->Dictionary[$Code])) {
            return $this->Dictionary[$Code];
        }

        return $Code;
    }

    /**
     * Should be used in extension to set new definitions.
     * This way, if a translation exists in the translation file,
     * the definition in the extension will not override it.
     * @param string $Code Code-word
     * @param string $Definition dfeault definition
     * @return void
     */
    function SetDefinition($Code, $Definition)
    {
        if (!isset($this->Dictionary[$Code])) {
            $this->Dictionary[$Code] = $Definition;
        }
    }

    /**
     * {@link Session::Start() Authenticate} user by its session or its "remember me" cookie;
     * set {@link $Authenticator} and {@link $Session}.
     * @return void
     */
    function StartSession()
    {
        $session = Session::getInstance();
        $session->Start();
        // The style url (as defined by the user session)
        if (@$session->User) {
            $this->StyleUrl = $session->User->StyleUrl;
            // Make sure that the Database object knows what the StyleUrl is
            Database::getInstance()->StyleUrl = $this->StyleUrl;
        }
    }

    /**
     * Destructor; unset all the properties.
     */
    function Unload()
    {
        unset($this->WarningCollector);
        unset($this->ErrorManager);
        unset($this->SqlCollector);
        unset($this->SelfUrl);
        unset($this->StyleUrl);
        unset($this->Mode);
        unset($this->BodyAttributes);
        unset($this->PageTitle);
        unset($this->StringManipulator);
        unset($this->Dictionary);
        unset($this->Configuration);
        unset($this->DelegateCollection);
        unset($this->DatabaseTables);
        unset($this->DatabaseColumns);
        unset($this->PassThruVars);
    }
}